package com.g13.virtualpethospital.controller;

import com.g13.virtualpethospital.common.EntityCommon;
import com.g13.virtualpethospital.common.Result;
import com.g13.virtualpethospital.entity.UserEntity;
import com.g13.virtualpethospital.exceptions.UserException;
import com.g13.virtualpethospital.service.UserService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.List;

import static com.g13.virtualpethospital.common.EntityCommon.RoleType.SUPERADMIN;
import static com.g13.virtualpethospital.common.EntityCommon.RoleType.USER;

/**
 * @Title: UserController
 * @Author yyj1205
 * @Package com.g13.virtualpethospital.controller
 * @Date 24/3/2024 20:11
 * @description: ...
 */

@Slf4j
@RestController
@ApiModel("用户操作相关接口")
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 前台登录
     * @param username
     * @param pwd
     */

    @PostMapping(value = "/fore-login", produces = "application/json")
    @ApiOperation("前台登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名称", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "pwd", value = "密码", required = true, paramType = "body", dataType = "String")
    })
    public Result<String> ForeLogin(@NotNull @RequestBody UserLogin userLogin) {
        try{
            String username = userLogin.username;
            String pwd = userLogin.pwd;
            if(username.isEmpty()) { return Result.fail("请输入用户名！"); }
            if(pwd.isEmpty()) { return Result.fail("请输入密码！"); }
            userService.login(username, pwd);
            UserEntity userEntity = userService.findUserByUserName(username).get(0);
            String id = userEntity.getId();
            return Result.success(id);
        } catch (UserException e) {
            if(e.getMessage().equals(UserException.UserErrorCode.FIND_NO_USER)) {
                return Result.fail("用户不存在！");
            }
            if(e.getMessage().equals(UserException.UserErrorCode.ERROR_PWD)){
                return Result.fail("密码错误！");
            }
            return Result.fail("出现异常情况，请检查代码！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * （前台）修改用户信息
     * @param userEntity（不包含权限）
     */

    @PutMapping(value = "/fore-update-user", produces = "application/json")
    @ApiOperation("修改用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "username", value = "用户名称", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "pwd", value = "密码", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "gender", value = "性别", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "tel", value = "电话", required = true, paramType = "body", dataType = "String")
    })
    public Result<UserEntity> UpdateUser(@NotNull @RequestBody UserUpdater userUpdater) {
        try {
            String id = userUpdater.getId();
            String username = userUpdater.getUsername();
            String tel = userUpdater.getTel();
            UserEntity userEntity = new UserEntity(id, username, userUpdater.pwd, null, userUpdater.gender, tel);
            if(UserCompleted(userEntity)) {
                if(UsernameDuplicated(username, id)) {
                    return Result.fail("用户名已被使用！", userEntity);
                }
                if(TelDuplicated(tel, id)) {
                    return Result.fail("手机号已被使用！", userEntity);
                }
                userService.updateUser(userEntity, id);
                return Result.success(userEntity);
            }
            return Result.fail("请完善用户信息！", userEntity);
        } catch (UserException e) {
            if(e.getMessage().equals(UserException.UserErrorCode.FIND_NO_USER)) {
                return Result.fail("用户不存在！");
            }
            return Result.fail("出现异常情况，请检查代码！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 用户注册
     * @param username
     * @param pwd
     * @param gender
     * @param tel
     */

    @PostMapping(value = "/regis", produces = "application/json")
    @ApiOperation("用户注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名称", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "pwd", value = "密码", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "gender", value = "性别", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "tel", value = "电话", required = true, paramType = "body", dataType = "String")
    })
    public Result<UserEntity> Register(@NotNull @RequestBody UserRegister userRegister) {
        try{
            String username = userRegister.username;
            String pwd = userRegister.pwd;
            String gender = userRegister.gender;
            String tel = userRegister.tel;
            UserEntity userEntity = new UserEntity(null, username, pwd, USER, gender, tel);
            if(UserCompleted(userEntity)) {
                if(!userService.findUserByUserName(username).isEmpty()) {
                    return Result.fail("用户名已被使用！");
                }
                if(!userService.findUserByTel(tel).isEmpty()){
                    return Result.fail("手机号已被使用！");
                }
                userService.register(userEntity);
                return Result.success(userEntity);
            }
            return Result.fail("存在未填项，请完善用户信息！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 后台登录
     * @param username
     * @param pwd
     */

    @PostMapping(value = "/back-login", produces = "application/json")
    @ApiOperation("后台登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名称", required = true, paramType = "body", dataType = "String"),
            @ApiImplicitParam(name = "pwd", value = "密码", required = true, paramType = "body", dataType = "String")
    })
    public Result<EntityCommon.RoleType> BackLogin(@NotNull @RequestBody UserLogin userLogin) {
        try{
            String username = userLogin.username;
            String pwd = userLogin.pwd;
            if(username.isEmpty()) { return Result.fail("请输入用户名！"); }
            if(pwd.isEmpty()) { return Result.fail("请输入密码！"); }
            userService.login(username, pwd);
            UserEntity userEntity = userService.findUserByUserName(username).get(0);
            EntityCommon.RoleType role = userEntity.getRole();
            if(role == USER) { return Result.fail("没有足够权限！"); }
            //额外添加了对于普通用户的登录检测（24/04/07 9：18）
            return Result.success(role);
        } catch (UserException e) {
            if(e.getMessage().equals(UserException.UserErrorCode.FIND_NO_USER)) {
                return Result.fail("用户不存在！");
            }
            if(e.getMessage().equals(UserException.UserErrorCode.ERROR_PWD)){
                return Result.fail("密码错误！");
            }
            return Result.fail("出现异常情况，请检查代码！");
        } catch (RuntimeException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取全部用户列表
     */

    @GetMapping(value = "/get-all-users", produces = "application/json")
    @ApiOperation("获取全部用户列表")
    public Result<List> GetAllUsers() {
        try{
            List<UserEntity> userEntities = userService.findAllUser();
            if(userEntities.isEmpty()) {
                return Result.fail("没有用户信息！");
            }
            return Result.success(userEntities);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除用户
     * @param id
     * @param role
     */

    @DeleteMapping(value = "/delete-user", produces = "application/json")
    @ApiOperation("删除用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "role", value = "用户权限", required = true, paramType = "query", dataType = "EntityCommon.roleType")
    })
    public Result<UserEntity> DeleteUser(@NotNull @RequestParam("id") String id,
                                         @NotNull @RequestParam("role") EntityCommon.RoleType role) {
        try{
            if(role != SUPERADMIN) {
                return Result.fail("没有足够权限！");
            }
            List<UserEntity> userEntities = userService.findUserById(id);
            if(userEntities.isEmpty()) { return Result.fail("用户不存在！"); }
            UserEntity user = userEntities.get(0);
            //这里如果id不存在直接get(0)会导致500错误，只能前置一个id存在检测避免意外（尽管delete方法里有检测，但其不返回用户容器，只能这么做了）
            //同时也意外包括了id为空的情况（输出与id不存在一致）（24/04/06 22：44）
            userService.deleteUser(id);
            return Result.success(user);
        } catch (UserException e) {
            if(e.getMessage().equals(UserException.UserErrorCode.FIND_NO_USER)) {
                return Result.fail("用户不存在！");
            }
            if(e.getMessage().equals(UserException.UserErrorCode.DEL_FAIL)){
                return Result.fail("删除失败！");
            }
            return Result.fail("出现异常情况，请检查代码！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 新增用户
     * @param userEntity
     * @param role
     */

    @PostMapping(value = "/add-user", produces = "application/json")
    @ApiOperation("新增用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userEntity", value = "用户实体", required = true, paramType = "body", defaultValue = "Object"),
            @ApiImplicitParam(name = "role", value = "用户权限", required = true, paramType = "body", dataType = "entityCommon.roleType")
    })
    public Result<UserEntity> AddUser(@NotNull @RequestBody UserManager userManager) {
        try {
            EntityCommon.RoleType role = userManager.role;
            UserEntity userEntity = userManager.userEntity;
            if(role != SUPERADMIN) {
                return Result.fail("没有足够权限！", userEntity);
            }
            if(UserCompleted(userEntity)&&userEntity.getRole() != null) {
                //新增了对于用户权限是否设置的检测（24/04/07 9：25）
                if(!userService.findUserByUserName(userEntity.getUsername()).isEmpty()) {
                    return Result.fail("用户名已被使用！", userEntity);
                }
                if(!userService.findUserByTel(userEntity.getTel()).isEmpty()) {
                    return Result.fail("手机号已被使用！", userEntity);
                }
                userService.register(userEntity);
                return Result.success(userEntity);
            }
            return Result.fail("存在未填项，请完善用户信息！", userEntity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * （管理员）修改用户信息
     * @param userEntity
     * @param role
     */

    @PutMapping(value = "/update-user", produces = "application/json")
    @ApiOperation("修改用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userEntity", value = "用户实体", required = true, paramType = "body", defaultValue = "Object"),
            @ApiImplicitParam(name = "role", value = "用户权限", required = true, paramType = "body", dataType = "entityCommon.roleType")
    })
    public Result<UserEntity> UpdateUser(@NotNull @RequestBody UserManager userManager) {
        try {
            EntityCommon.RoleType role = userManager.role;
            UserEntity userEntity = userManager.userEntity;
            if(role != SUPERADMIN) {
                return Result.fail("没有足够权限！", userEntity);
            }
            if(UserCompleted(userEntity)&&userEntity.getRole() != null) {
                //新增了对于用户权限是否设置的检测（24/04/07 9：25）
                String username = userEntity.getUsername();
                String tel = userEntity.getTel();
                String id = userEntity.getId();
                if(UsernameDuplicated(username, id)) {
                    return Result.fail("用户名已被使用！", userEntity);
                }
                if(TelDuplicated(tel, id)) {
                    return Result.fail("手机号已被使用！", userEntity);
                }
                userService.updateUser(userEntity, userEntity.getId());
                return Result.success(userEntity);
            }
            return Result.fail("请完善用户信息！", userEntity);
        } catch (UserException e) {
            if(e.getMessage().equals(UserException.UserErrorCode.FIND_NO_USER)) {
                return Result.fail("用户不存在！");
            }
            return Result.fail("出现异常情况，请检查代码！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * （私有函数）检查用户类中是否存在空值
     * 用户名，密码，性别，电话均不为空返回真，否则返回假
     * @param userEntity
     */

    private boolean UserCompleted(UserEntity userEntity) {
        boolean username = userEntity.getUsername().isEmpty();
        boolean pwd = userEntity.getPwd().isEmpty();
        boolean gender = userEntity.getGender().isEmpty();
        boolean tel = userEntity.getTel().isEmpty();
        return !username && !pwd && !gender && !tel;
    }

    /**
     * （私有函数）检查修改的用户名是否合法
     * 检查用户名是否修改，若修改，检查用户名是否重复，若重复返回真，否则返回假
     * 注：这里如果不先做id存在性检查会导致500报错，因此尽管用到该功能的接口后面往往已经有了id存在性检查，还是需要提前做一次检查
     * @param username
     * @param id
     */

    private boolean UsernameDuplicated(String username, String id) throws UserException {
        List<UserEntity> userEntities = userService.findUserById(id);
        if(userEntities.isEmpty()) { throw new UserException(UserException.UserErrorCode.FIND_NO_USER); }
        UserEntity userEntity_before = userEntities.get(0);
        if(!username.equals(userEntity_before.getUsername())) {
            if(!userService.findUserByUserName(username).isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * （私有函数）检查修改的手机号是否合法
     * 检查手机号是否修改，若修改，检查手机号是否重复，若重复返回真，否则返回假
     * 注：这里如果不先做id存在性检查会导致500报错，因此尽管用到该功能的接口后面往往已经有了id存在性检查，还是需要提前做一次检查
     * @param tel
     * @param id
     */

    private boolean TelDuplicated(String tel, String id) throws UserException {
        List<UserEntity> userEntities = userService.findUserById(id);
        if(userEntities.isEmpty()) { throw new UserException(UserException.UserErrorCode.FIND_NO_USER); }
        UserEntity userEntity_before = userEntities.get(0);
        if(!tel.equals(userEntity_before.getTel())) {
            if(!userService.findUserByTel(tel).isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 用户登录类
     * 包含用户名和密码
     * @param username
     * @param pwd
     */

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class UserLogin {
        private String username;
        private String pwd;
    }

    /**
     * 用户注册类
     * 包含用户名，密码，性别和手机号
     * @param username
     * @param pwd
     * @param gender
     * @param tel
     */

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class UserRegister {
        private String username;
        private String pwd;
        private String gender;
        private String tel;
    }

    /**
     * 用户更新类
     * 包含id，用户名，密码，性别和手机号
     * @param id
     * @param username
     * @param pwd
     * @param gender
     * @param tel
     */

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class UserUpdater {
        private String id;
        private String username;
        private String pwd;
        private String gender;
        private String tel;
    }

    /**
     * 管理用户类
     * 包含被操作用户容器和当前用户权限
     * @param userEntity
     * @param role
     */

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class UserManager {
        private UserEntity userEntity;
        private EntityCommon.RoleType role;
    }
}
